/* 
 * File:   MenuNewGame.cpp
 * Author: agu
 * 
 * Created on 16 de junio de 2014, 20:21
 */

#include "client_MenuNewGame.h"
#include <iostream>
#include <sstream>
#include <vector>
#define LARGO 5
using std::cout;
using std::endl;
using std::vector;
using std::stringstream;

MenuNewGame::MenuNewGame() {
    this->builder = Gtk::Builder::create();
    try {
        this->builder->add_from_file("gladeInterfaces/menuNewGame.glade");
    } catch (const Glib::FileError& ex) {
        std::cout << "FileError: " << ex.what() << std::endl;

    } catch (const Glib::MarkupError& ex) {
        std::cout << "MarkupError: " << ex.what() << std::endl;

    } catch (const Gtk::BuilderError& ex) {
        std::cout << "BuilderError: " << ex.what() << std::endl;
    }

}

void MenuNewGame::loadWidgets() {
    this->builder->get_widget("window", this->window);
    this->builder->get_widget("buttonBack", this->buttonBack);
    this->builder->get_widget("buttonAccept", this->buttonAccept);
    this->builder->get_widget("buttonOk", this->buttonOk);
    this->builder->get_widget("entryName", this->entryName);
    this->builder->get_widget("comboCampania", this->comboCampaign);
    this->builder->get_widget("textView", this->textView);
    this->builder->get_widget("image", this->image);
    this->builder->get_widget("message", this->message);

}

void MenuNewGame::connectWidgets() {
    this->window->signal_hide().connect(sigc::mem_fun(this, &MenuNewGame::close));
    this->buttonBack->signal_clicked().connect(sigc::mem_fun(this, &MenuNewGame::back));
    this->buttonAccept->signal_clicked().connect(sigc::mem_fun(this, &MenuNewGame::accept));
    this->buttonOk->signal_clicked().connect(sigc::mem_fun(this, &MenuNewGame::ok));
    this->comboCampaign->signal_changed().connect(sigc::mem_fun(this, &MenuNewGame::onComboChanged));
    this->campSelect = -1;
    this->image->hide();
}

MenuNewGame::~MenuNewGame() {
}

void MenuNewGame::run() {
    this->loadWidgets();
    this->createModel();
    this->connectWidgets();
    this->window->show();
}

void MenuNewGame::close() {
    this->window->close();
}

void MenuNewGame::back() {
    this->window->set_visible(false);
    this->windowsBack->set_visible(true);
}

void MenuNewGame::ok() {
    this->message->hide();
}

void MenuNewGame::accept() {
    string inputText(this->entryName->get_chars(0, -1));
    if (this->campSelect >= 0) {
        if (!inputText.empty()) {
            this->window->hide();
            //Avisarle al server que partida se creo
            string msj = agregarLargo("C|" + inputText + "|" + campaignsInfo.at(campSelect).at(0)+"|"+std::to_string(campSelect));
            this->send(msj);
            msj= this->recv();//aca recibo la letra que me referencia que color de jugador soy            
            this->watingRoom.setSocket(this->socket);
            this->watingRoom.setPlayerCode(msj);//debo recibirlo del server
            this->watingRoom.setGameName(campaignsInfo.at(campSelect).at(0));
            this->watingRoom.setImagePath(campaignsInfo.at(campSelect).at(1));
            this->watingRoom.setWindowsBack(this->window);
            this->watingRoom.userCreatorActive();
            this->watingRoom.run();
        } else {
            //sale por cartel de mensaje
            Glib::ustring mensaje = "Debe completar con un nombre ";
            this->message->set_secondary_text(mensaje, false);
            this->message->show();
        }
    } else {
        //sale por cartel de mensaje
        Glib::ustring mensaje = "Debe seleccionar una partida";
        this->message->set_secondary_text(mensaje, false);
        this->message->show();
    }
}

void MenuNewGame::setWindowsBack(Gtk::Window *windowBack) {
    this->windowsBack = windowBack;
}

void MenuNewGame::setSocket(Client_socket s) {
    this->socket = s;
}

void MenuNewGame::createModel() {
    this->send("00002|A");
    this->getCampaignsInfo();
    refTreeModelCampanias = Gtk::ListStore::create(columnsCampanias);
    comboCampaign->set_model(refTreeModelCampanias);
    Gtk::TreeModel::Row row = *(refTreeModelCampanias->append());
    this->loadCampaignsInfo(row);
    comboCampaign->set_active(row);
    comboCampaign->pack_start(columnsCampanias.colCampName);
}

void MenuNewGame::onComboChanged() {
    Gtk::TreeModel::iterator iter = comboCampaign->get_active();
    if (iter) {
        Gtk::TreeModel::Row row = *iter;
        if (row) {
            Glib::ustring name = row[columnsCampanias.colCampName];
            int indice = -1;
            for (unsigned int i = 0; i < campaignsInfo.size(); i++) {
                if (campaignsInfo.at(i).at(0).compare(name) == 0) {
                    indice = i;
                }
            }
            this->campSelect = indice;
            //Buscar en el campaignsInfo la campaña con ese nombre
            Glib::RefPtr<Gtk::TextBuffer> textBuffer = Gtk::TextBuffer::create();
            Glib::ustring buffer = "Nombre: " + name + "\n" +
                    "Dificultad: " + campaignsInfo.at(indice).at(2) + "\n" +
                    "Cantidad de Jugadores:" + campaignsInfo.at(indice).at(3);
            textBuffer->set_text(buffer);
            textView->set_buffer(textBuffer);     
            this->image->set("img/menu/labels/label.png");
            this->image->show();
        }
    } else
        std::cout << "invalid iter" << std::endl;
}

string MenuNewGame::recv() {
    string largoALeer;
    if (this->socket.recibir(&largoALeer, LARGO) == -1) {        
    }
    int largoInfo = stoi(largoALeer);
    string buffer;
    if (this->socket.recibir(&buffer, largoInfo) == -1) {
    }
    buffer.erase(0, 1);
    return buffer;
}

void MenuNewGame::send(const string msj) {
    int tam = msj.size();
    this->socket.enviar(msj, tam);
}

void MenuNewGame::getCampaignsInfo() {
    string info = this->recv();
    //    string info = "campaña1|ruta1|2|3|campaña2|ruta2|3|4";    
    vector<string> datos = this->getElementos(info, '|');
    vector<string> campInfo;
    for (unsigned int i = 0; i < (datos.size() / 4); i++) {
        for (unsigned int j = 0; j < 4; j++) {
            campInfo.push_back(datos.at(i * 4 + j));
        }
        campaignsInfo.push_back(campInfo);
        campInfo.clear();
    }
}

void MenuNewGame::loadCampaignsInfo(Gtk::TreeModel::Row row) {
    for (unsigned int i = 0; i < campaignsInfo.size(); i++) {
        row = *(refTreeModelCampanias->append());
        row[columnsCampanias.colCampName] = campaignsInfo.at(i).at(0);
    }
}

vector<string> MenuNewGame::getElementos(const string& linea, char separador) {
    vector<string> elementos;
    stringstream ss(linea);
    string item;
    while (std::getline(ss, item, separador)) {
        elementos.push_back(item);
    }
    return elementos;
}

string MenuNewGame::agregarLargo(string buffer) {
    int largo = buffer.size() + 1;    
    char* formato = (char*) malloc((LARGO + 1) * sizeof (char));
    snprintf(formato, LARGO + 1, "%.5d", largo);
    string aux;
    aux.append(string(formato));
    aux.append("|");
    aux.append(buffer);
    free(formato);
    return aux;
}